//-------------------------------------------------------------------
//	Copyright (c) 2012-2014 Zhirnov Andrey
//	This file is part of the "UXGEN-ES" project.
//	See copyright notice in "Engine.h".
//-------------------------------------------------------------------

#pragma once

#include "UI/Widgets/Widget.h"

namespace Engine
{
namespace UI
{

	class GroupSwitch;
	SHARED_POINTER( GroupSwitch );



	//
	// Group Switch
	//

	class GroupSwitch : public Widget
	{
		friend struct ::MetaData::GroupSwitchCfg;

	// variables
	protected:
		WidgetPtr	_currentGroup;


	// methods
	public:
		GroupSwitch (EWidget::type wgtType, const EngineSubSystemsRef ess);
		~GroupSwitch ();


		bool SetCurrentGroup (uint index);
		bool SetCurrentGroup (uni_c_string name);
		uint GetCurrentGroup () const;
		
		virtual bool ProcessMessage (const WidgetMsg &msg) override;

		static GroupSwitchPtr	New (const EngineSubSystemsRef ess);


	protected:
		bool _Arrange (const WidgetMsg &msg);
		bool _Update (const WidgetMsg &msg);
		bool _Draw (const WidgetMsg &msg);

		bool _Attach (const WidgetMsg::Attach &msg);
		bool _Detach (const WidgetMsg::Attach &msg);
	};



	
/*
=================================================
	constructor
=================================================
*/
	inline GroupSwitch::GroupSwitch (EWidget::type wgtType, const EngineSubSystemsRef ess) : Widget(wgtType, ess)
	{}
	
/*
=================================================
	destructor
=================================================
*/
	inline GroupSwitch::~GroupSwitch ()
	{}
		
/*
=================================================
	SetCurrentGroup
=================================================
*/
	inline bool GroupSwitch::SetCurrentGroup (uint index)
	{
		_stateChanged = true;

		if ( index < GetWidgets().Count() )
		{
			_currentGroup = GetWidgets()[ index ];
			return true;
		}
		_currentGroup = null;
		return false;
	}
	
/*
=================================================
	SetCurrentGroup
=================================================
*/
	inline bool GroupSwitch::SetCurrentGroup (uni_c_string name)
	{
		_stateChanged = true;

		FOR( i, GetWidgets() )
		{
			if ( GetWidgets()[i]->GetName() == name )
			{
				_currentGroup = GetWidgets()[i];
				return true;
			}
		}
		_currentGroup = null;
		return false;
	}

/*
=================================================
	GetCurrentGroup
=================================================
*/
	inline uint GroupSwitch::GetCurrentGroup () const
	{
		usize	idx = -1;
		GetWidgets().Find( idx, _currentGroup );
		return idx;
	}

/*
=================================================
	ProcessMessage
=================================================
*/
	inline bool GroupSwitch::ProcessMessage (const WidgetMsg &msg)
	{
		typedef WidgetMsg	WM;

		switch ( msg.GetType() )
		{
			case WM::UPDATE  :	return _Update( msg );
			case WM::DRAW :		return _Draw( msg );
			case WM::ARRANGE :	return _Arrange( msg );
			case WM::ATTACH :	return _Attach( msg.To< WM::Attach >() );
			case WM::DETACH :	return _Detach( msg.To< WM::Attach >() );
		}

		return Widget::ProcessMessage( msg );
	}

/*
=================================================
	New
=================================================
*/
	inline GroupSwitchPtr GroupSwitch::New (const EngineSubSystemsRef ess)
	{
		return BaseObject::_New( new GroupSwitch( EWidget::GROUP, ess ) );
	}
	
/*
=================================================
	_Arrange
=================================================
*/
	inline bool GroupSwitch::_Arrange (const WidgetMsg &msg)
	{
		typedef WidgetMsg		WM;

		ArrangeHelper const &	helper		= *msg.To< WM::Arrange >().helper;
		WidgetLayout const &	layout		= helper.GetLayout( _layouts );
		bool const				auto_size	= helper.IsAutoSize( layout );

		CHECK_ERR( not auto_size );
		
		_visibleForLayout = helper.IsVisibleForLayout( _layoutMask );

		if ( not _visibleForLayout )
			return true;
		
		helper.Arrange( _region, layout, _parent->GetRegion(), _parent->GetDockRegion() );
		
		_dockRegion = _region;

		if ( _currentGroup.IsNull() ) {
			SetCurrentGroup( 0 );
		}
		else {
			_currentGroup->ProcessMessage( msg );
		}

		_stateChanged = true;
		return true;
	}

/*
=================================================
	_Update
=================================================
*/
	inline bool GroupSwitch::_Update (const WidgetMsg &msg)
	{
		if ( not IsVisible() or _currentGroup.IsNull() )
			return true;
		
		_CheckChangedOnUpdate( msg );

		_currentGroup->ProcessMessage( msg );
		return true;
	}
	
/*
=================================================
	_Draw
=================================================
*/
	inline bool GroupSwitch::_Draw (const WidgetMsg &msg)
	{
		if ( not IsVisible() or _currentGroup.IsNull() )
			return true;
		
		_currentGroup->ProcessMessage( msg );
		return true;
	}
	
/*
=================================================
	_Attach
=================================================
*/
	inline bool GroupSwitch::_Attach (const WidgetMsg::Attach &msg)
	{
		CHECK_ERR( msg.widget != null );
		CHECK_ERR( msg.widget->GetType() == EWidget::GROUP );

		return Widget::_Attach( msg );
	}

/*
=================================================
	_Detach
=================================================
*/
	inline bool GroupSwitch::_Detach (const WidgetMsg::Attach &msg)
	{
		bool	select_first = false;

		_stateChanged = true;

		if ( _currentGroup == msg.widget )
		{
			select_first  = true;
			_currentGroup = null;
		}

		if ( Widget::_Detach( msg ) )
		{
			if ( select_first )
			{
				SetCurrentGroup( 0 );
			}
			return true;
		}
		return false;
	}


}	// UI
}	// Engine